package com.boyon.common.tree;

import java.util.ArrayList;
import java.util.List;

/**
 * ClassName:TreeAssembly <br/>
 * Function: tree实现方法. <br/>
 * Date: 2018年3月15日 上午12:00:28 <br/>
 * 
 * @author sunshulin
 * @version
 * @since JDK 1.8
 * @see
 */
public abstract class TreeAssembly<T, V> {

	/**
	 * 
	 * createTree:创建树形结构通用处理方法. <br/>
	 * 
	 * @author sunshulin
	 * @param entities
	 * @return
	 * @since JDK 1.8
	 */
	public T createTree(List<T> entities) {
		return createTree(entities, null);
	}

	/**
	 * 
	 * createTree:创建树形结构通用处理方法,. <br/>
	 * 
	 * @author sunshulin
	 * @param entities
	 * @param exits
	 * @return
	 * @since JDK 1.8
	 */
	public T createTree(List<T> entities, List<V> exits) {
		T root = createT();
		// 复制原始数据
		List<T> copies = new ArrayList<>(entities);
		// 清空数据列表
		List<T> clears = new ArrayList<>();
		for (T entity : entities) {
			handler(entity);
			handlerContains(exits, entity);
			// 当前节点ID
			V entityId = getId(entity);
			// 是否是根据点
			if (isParent(entity)) {
				addChildren(root, entity);
			}
			// 查询子节点数据
			for (T node : copies) {
				handler(node);
				// 节点根节点
				V parentId = getParent(node);
				if (!isParent(node) && parentId.equals(entityId)) {
					// 非根节点,父节点ID=节点ID
					addChildren(entity, node);
					clears.add(node);
				} else if (isParent(node)) {
					clears.add(node);
				}
			}
			copies.removeAll(clears);
			clears.clear();
		}
		return root;
	}

	/**
	 * 
	 * handlerExits:处理数据节点. <br/>
	 * 
	 * @author sunshulin
	 * @param ids
	 * @param entity
	 * @since JDK 1.8
	 */
	private void handlerContains(List<V> ids, T entity) {
		if (ids != null) {
			handlerContains(entity, ids.contains(getId(entity)));
		}
	}

	/**
	 * 
	 * createT:创建实体bean. <br/>
	 * 
	 * @author sunshulin
	 * @since JDK 1.8
	 */
	public abstract T createT();

	/**
	 * 
	 * getId:节点唯一标识. <br/>
	 * 
	 * @author sunshulin
	 * @param entity
	 * @return
	 * @since JDK 1.8
	 */
	public abstract V getId(T entity);

	/**
	 * 
	 * handlerContains:处理节点包含关系. <br/>
	 * 
	 * @author sunshulin
	 * @param entity
	 * @param isContain
	 * @since JDK 1.8
	 */
	public abstract void handlerContains(T entity, boolean isContain);

	/**
	 * 
	 * getParent:获取上级节点. <br/>
	 * 
	 * @author sunshulin
	 * @param entity
	 * @return
	 * @since JDK 1.8
	 */
	public abstract V getParent(T entity);

	/**
	 * 
	 * isParent:是否根节点. <br/>
	 * 
	 * @author sunshulin
	 * @param entity
	 * @return
	 * @since JDK 1.8
	 */
	public abstract boolean isParent(T entity);

	/**
	 * 
	 * addChildren:添加节点. <br/>
	 * 
	 * @author sunshulin
	 * @param entity
	 * @param node
	 * @since JDK 1.8
	 */
	public abstract void addChildren(T entity, T node);

	/**
	 * 
	 * handler:处理数据节点. <br/>
	 * 
	 * @author sunshulin
	 * @param entity
	 * @since JDK 1.8
	 */
	public abstract void handler(T entity);
}
